package gatperdut.chato.core.threads;

import gatperdut.chato.constants.CSConstantsString;
import gatperdut.chato.core.characters.BaseController;
import gatperdut.chato.core.craft.CraftController;
import gatperdut.chato.core.craft.CraftStepController;
import gatperdut.chato.core.craft.CraftToolController;
import gatperdut.chato.core.item.FoodController;
import gatperdut.chato.core.item.ItemController;
import gatperdut.chato.model.Chato.Craft.CraftCheck;
import gatperdut.chato.model.Chato.Craft.CraftTool;
import gatperdut.chato.model.Chato.Craft.GeneratedItem;
import gatperdut.chato.model.Chato.Item.ItemTemplate;

import java.util.Collection;
import java.util.List;

public class CraftThread extends Thread {

    private final CraftController craftController;

    private final BaseController baseController;

    public CraftThread( BaseController baseController, CraftController craftController ) {
        this.craftController = craftController;
        this.baseController = baseController;
    }

    @Override
    public void run() {
        if ( !checkTools( getCraftController().getCraftToolToController().values() ) ) {
            getBaseController().setCraftThread( null );
            return;
        }

        getBaseController().getEchoes().txCraftInitialMessage( getCraftController() );

        try {
            sleep( getCraftController().getCraft().getTime() * 1000 );
        }
        catch ( InterruptedException e ) {
            return;
        }

        checkReusability( getCraftController().getCraftToolToController().values() );

        for ( CraftStepController csc : getCraftController().getCraftStepToController().values() ) {
            if ( !checkTools( csc.getCraftToolToController().values() ) ) {
                return;
            }

            getBaseController().getEchoes().txCraftStepInitialMessage( csc );
            try {
                sleep( csc.getCraftStep().getTime() * 1000 );
            }
            catch ( InterruptedException e ) {
                return;
            }

            if ( !checkAccomplishment( csc.getCraftStep().getChecks() ) ) {
                getBaseController().getEchoes().txCraftStepFailureMessage( csc );
                return;
            }

            checkReusability( csc.getCraftToolToController().values() );

            checkItemGeneration( csc.getCraftStep().getGeneratedItems() );
        }

        getBaseController().getEchoes().txCraftSuccessMessage( getCraftController() );

        getBaseController().setCraftThread( null );
    }

    private boolean checkAccomplishment( List<CraftCheck> craftChecks ) {
        for ( CraftCheck cc : craftChecks ) {
            int value = (int) ( Math.random() * ( 100 ) );
            if ( value > cc.getChance() ) {
                return false;
            }
        }

        return true;
    }

    private void checkItemGeneration( List<GeneratedItem> generatedItems ) {
        ItemController ic;
        ItemTemplate it;
        for ( GeneratedItem gi : generatedItems ) {
            it = gi.getItemTemplate();
            ic = getBaseController().getChatoServer().getItemHandler().genItemController( it );
            if ( it.getStack() != null || it.getFood() != null ) {
                ic.getAmountController().setCurrent( gi.getAmount() );
            }
        }
    }

    private void checkReusability( Collection<CraftToolController> tools ) {
        for ( CraftToolController ctc : tools ) {
            if ( !ctc.getCraftTool().isReusable() ) {
                if ( ctc.getChosenTool().isStackable() ) {
                    ctc.getChosenTool().getAmountController().setCurrent( ctc.getChosenTool().getAmountController().getCurrent() - 1 );
                    if ( ctc.getChosenTool().getAmountController().getCurrent() == 0 ) {
                        ctc.getChosenTool().junk();
                    }
                }
                else if ( ctc.getChosenTool().isEatable() ) {
                    FoodController fc = (FoodController) ctc.getChosenTool().getAmountController();
                    fc.decrease( 1 );
                    if ( fc.isEmpty() ) {
                        ctc.getChosenTool().junk();
                    }
                }
                else {
                    ctc.getChosenTool().junk();
                }
            }
        }
    }

    public boolean checkTools( Collection<CraftToolController> tools ) {
        for ( CraftToolController ctt : tools ) {
            for ( ItemTemplate it : ctt.getCraftTool().getOrList() ) {
                ItemController ic;
                boolean found = false;
                switch ( ctt.getCraftTool().getLocation() ) {
                case ANYWHERE:
                    ic = getBaseController().getInventoryController().getItemControllerMatchingTemplate( it );
                    if ( ic == null ) {
                        ic = getBaseController().getRoomController().getInventoryController().getItemControllerMatchingTemplate( it );
                    }
                    break;
                case IN_HAND:
                    ic = getBaseController().getInventoryController().getItemControllerMatchingTemplate( it );
                    break;
                case IN_ROOM:
                    ic = getBaseController().getRoomController().getInventoryController().getItemControllerMatchingTemplate( it );
                    break;
                default:
                    throw new IllegalArgumentException( "Craft tool with unknown tool location." );

                }
                if ( ic != null ) {
                    ctt.setChosenTool( ic );
                    found = true;
                }
                else {
                    warnMissingCraftTool( ctt.getCraftTool() );
                }
                if ( !found ) {
                    return false;
                }
                else {
                    break;
                }
            }
        }

        return true;
    }

    private void warnMissingCraftTool( CraftTool ct ) {
        StringBuilder sb;
        switch ( ct.getLocation() ) {
        case ANYWHERE:
            sb = new StringBuilder( "You need one of the following for this craft to work:" + CSConstantsString.NEWLINE );
            break;
        case IN_HAND:
            sb = new StringBuilder( "You should be holding one of the following for this craft to work:" + CSConstantsString.NEWLINE );
            break;
        case IN_ROOM:
            sb = new StringBuilder( "One of the following should be nearby for this craft to work:" + CSConstantsString.NEWLINE );
            break;
        default:
            throw new IllegalArgumentException( "Craft tool with unknown tool location." );

        }
        boolean firstAdded = false;
        for ( ItemTemplate itList : ct.getOrList() ) {
            if ( firstAdded ) {
                sb.append( ", " );
            }
            else {
                firstAdded = true;
                sb.append( itList.getShortDesc() );
            }
        }
        getBaseController().tx( sb.toString() );
    }

    @Override
    public void interrupt() {
        getBaseController().setCraftThread( null );
        super.interrupt();
    }

    public CraftController getCraftController() {
        return craftController;
    }

    public BaseController getBaseController() {
        return baseController;
    }
}
